package java8.time;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * @author ChangLiang
 * @date 2020/4/17
 */
public class App {

    @Test
    @DisplayName("获取今天的日期")
    public void test() {
        LocalDate today = LocalDate.now();
        System.out.println("today: " + today);
    }

    @Test
    @DisplayName("获取年月日信息")
    public void test2() {
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        int month = today.getMonthValue();
        int day = today.getDayOfMonth();
        System.out.println("year: " + year);
        System.out.println("month: " + month);
        System.out.println("day: " + day);
    }

    @Test
    @DisplayName("处理特定日期")
    public void test3() {
        LocalDate date = LocalDate.of(2018, 2, 6);
        System.out.println("自定义日期: " + date);
    }

    @Test
    @DisplayName("判断两个日期是否相等")
    public void test4() {
        LocalDate date1 = LocalDate.now();
        LocalDate date2 = LocalDate.of(2020, 4, 17);
        if (date1.equals(date2)) {
            System.out.println("time is equal");
        } else {
            System.out.println("time is not equal");
        }
    }

    @Test
    @DisplayName("检查像生日这种周期型事件")
    public void test5() {
        LocalDate date1 = LocalDate.now();
        LocalDate bornDay = LocalDate.of(2017, 2, 24);
        MonthDay bornMonthDay = MonthDay.of(bornDay.getMonth(), bornDay.getDayOfMonth());

        MonthDay currentMonthDay = MonthDay.from(date1);

        if (currentMonthDay.equals(bornMonthDay)) {
            System.out.println("today is your birthday");
        } else {
            System.out.println("today is not your birthday");
        }
    }

    @Test
    @DisplayName("获取当前时间")
    public void test6() {
        LocalTime time = LocalTime.now();
        System.out.println("获取到当前时间: " + time);
    }

    @Test
    @DisplayName("当前时间基础上修改时间")
    public void test7() {
        LocalTime time = LocalTime.now();
        LocalTime newTime = time.plusHours(3);
        System.out.println("3小时后时间为: " + newTime);
    }

    @Test
    @DisplayName("如何计算一周后的日期")
    public void test8() {
        LocalDate today = LocalDate.now();
        System.out.println("今天的日期为: " + today);
        LocalDate nextWeekDate = today.plus(1, ChronoUnit.WEEKS);
        System.out.println("一周后的日期为: " + nextWeekDate);
    }

    @Test
    @DisplayName("计算一年前或一年后的日期")
    public void test9() {
        LocalDate today = LocalDate.now();
        LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
        System.out.println("一年前日期: " + previousYear);
        LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
        System.out.println("一年后日期: " + nextYear);
    }

    @Test
    @DisplayName("Clock时钟类")
    public void test10() {
        Clock clock = Clock.systemUTC();
        System.out.println("Clock:" + clock.millis());
    }

    @Test
    @DisplayName("判断给定日期是早于还是晚于另一个日期")
    public void test11() {
        LocalDate date1 = LocalDate.now();
        LocalDate date2 = date1.plus(1, ChronoUnit.DAYS);
        if (date2.isAfter(date1)) {
            System.out.println("之后的日期: " + date2);
        }
        LocalDate date3 = date1.minus(1, ChronoUnit.DAYS);
        if (date3.isBefore(date1)) {
            System.out.println("之前的日期: " + date3);
        }
    }

    @Test
    @DisplayName("处理时区")
    public void test12() {
        ZoneId america = ZoneId.of("America/New_York");
        LocalDateTime localDateAndTime = LocalDateTime.now();
        ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localDateAndTime, america);
        System.out.println("current date and time in a particular timezone: " + dateAndTimeInNewYork);
    }

    @Test
    @DisplayName("使用YearMonth表示信用卡到其这类规定日期")
    public void test13() {
        YearMonth currentYearMonth = YearMonth.now();
        System.out.printf("%s has %d days%n", currentYearMonth, currentYearMonth.lengthOfMonth());
        YearMonth creditCardExpiry = YearMonth.of(2019, Month.FEBRUARY);
        System.out.printf("Your credit card expired on %s%n", creditCardExpiry);
    }

    @Test
    @DisplayName("检查闰年")
    public void test14() {
        LocalDate today = LocalDate.now();
        if (today.isLeapYear()) {
            System.out.println("this year is leap year");
        } else {
            System.out.println("this year is not a leap year");
        }
    }

    @Test
    @DisplayName("计算两个日期之间的天数和月数")
    public void test15() {
        LocalDate today = LocalDate.now();
        LocalDate java8Release = LocalDate.of(2020, 12, 14);
        Period periodToNextJavaRelease = Period.between(today, java8Release);
        System.out.printf("Months left between today and java8 release: %d months", periodToNextJavaRelease.getMonths());
    }

    @Test
    @DisplayName("获取当前的时间戳")
    public void test16() {
        Instant timestamp = Instant.now();
        System.out.println("what is value of this instant " + timestamp.toEpochMilli());

        // Date convert to Instant
        Date date = Date.from(timestamp);
        System.out.printf("timestamp:%s convert to date:%s%n", timestamp, date);

        // Instant Convert to Date
        Instant instant = date.toInstant();
        System.out.printf("date:%s convert to timestamp:%s%n", date, instant);
    }

    @Test
    @DisplayName("使用预定义的格式化工具去解析或格式化日期")
    public void test17() {
        String dateStr = "20180205";
        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(dateStr + "格式化后的日期为: " + date);
    }

    @Test
    @DisplayName("字符串互转日期类型")
    public void test18() {
        LocalDateTime dateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        // localDateTime -> String
        String str = dateTime.format(formatter);
        System.out.printf("日期%s转换为字符串%s%n", dateTime, str);

        // String -> LocalDateTime
        LocalDateTime dateTime2 = LocalDateTime.parse(str, formatter);
        System.out.printf("字符串%s转换为日期%s%n", str, dateTime2);
    }

    @Test
    @DisplayName("获取当前日期是星期几")
    public void test19() {
        DayOfWeek dayOfWeek = LocalDate.parse("2017-04-24").getDayOfWeek();
        // output MONDAY
        System.out.printf("2017-04-24 是 星期 %s%n ", dayOfWeek);
    }

    @Test
    @DisplayName("表示月份的序列值")
    public void test20() {
        int dayOfMonth = LocalDate.parse("2017-04-24").getDayOfMonth();
        System.out.printf("2017-04-24 是月中的第 %d 天%n", dayOfMonth);
    }

    @Test
    @DisplayName("给定日期的一天的开始")
    public void test21() {
        LocalDateTime beginningOfDay = LocalDate.parse("2017-04-24").atStartOfDay();
        // output 2017-04-24T00:00
        System.out.printf("2017-04-24 beginning of day is %s%n", beginningOfDay);
    }

    @Test
    @DisplayName("给定日期的月初的LocalDate")
    public void test22() {
        LocalDate firstDayOfMonth = LocalDate.parse("2017-04-24").with(TemporalAdjusters.firstDayOfMonth());
        System.out.printf("2017-04-24 beginning of day of month is %s%n", firstDayOfMonth);
    }

    @Test
    @DisplayName("一天中的最大，最小和中午时间可以通过LocalTime类中的常量获得")
    public void test23() {
        // 在执行数据库查询以查找给定时间范围内的记录时，非常有用
        LocalTime max = LocalTime.MAX;
        // output 23:59:59.999999999
        System.out.printf("max time is %s%n", max);

        LocalTime midnight = LocalTime.MIDNIGHT;
        // output 00:00
        System.out.printf("midnight time is %s%n", midnight);

        LocalTime min = LocalTime.MIN;
        // output 00:00
        System.out.printf("min time is %s%n", min);
    }

    @Test
    @DisplayName("获取两个时间点之间的时间差")
    public void test24() {
        LocalTime initTime = LocalTime.of(6, 30, 0);
        LocalTime finalTime = initTime.plus(Duration.ofSeconds(30));
        long seconds = Duration.between(finalTime, initTime).getSeconds();
        // -30
        System.out.printf("seconds between finalTime: %s and initTime: %s is %d%n", finalTime, initTime, seconds);

        long between = ChronoUnit.SECONDS.between(initTime, finalTime);
        // 30
        System.out.printf("seconds between initTime: %s and finalTime: %s is %d%n", initTime, finalTime, between);
    }

    @Test
    @DisplayName("获取时区所在的时间")
    public void test25() {
        LocalDateTime cnldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.printf("shanghai time: %s%n", cnldt);
        System.out.printf("shanghai milliseconds: %d%n", cnldt.toEpochSecond(ZoneOffset.ofHours(+8)));

        LocalDateTime ukldt = LocalDateTime.now(ZoneId.of("Europe/London"));
        System.out.printf("London time: %s%n", ukldt);
        System.out.printf("London UTC milliseconds: %d%n", cnldt.toEpochSecond(ZoneOffset.UTC));

        LocalDateTime usldt = LocalDateTime.now(ZoneId.of("America/Chicago"));
        System.out.printf("Chicago time: %s%n", usldt);
        System.out.printf("Chicago milliseconds: %d%n", cnldt.toEpochSecond(ZoneOffset.of("-6")));

    }


}
